import json

from fastapi import Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import _StreamingResponse

from app.auth.dependencies import get_token_from_request
from app.core.models import AccessToken
from app.core.security import decode_access_token, create_access_token


async def read_json_body(response: _StreamingResponse):
    body = b""
    async for chunk in response.body_iterator:
        body += chunk
    body_json = json.loads(body)
    return body_json


async def refresh_token_silently(request: Request, call_next):
    response = await call_next(request)
    if response.status_code == 200 and response.headers.get("Content-Type") == "application/json":
        body_json = await read_json_body(response)
        response = JSONResponse(
            content=body_json,
            status_code=response.status_code,
            headers=response.headers
        )
        if body_json and "new_token" in body_json and body_json["new_token"] is None:
            token = get_token_from_request(request)
            if token:
                payload = decode_access_token(token)
                if payload:
                    new_token = create_access_token(payload)
                    body_json["new_token"] = AccessToken(
                        access_token=new_token,
                        token_type="bearer"
                    ).dict()
                    response.content = body_json
                    response.set_cookie(key="token", value=new_token)
        response.headers["Content-Length"] = str(len(response.body))
    return response
